#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

//代码编译: gcc mmap_send.c -o send -lrt

#define SHM_NAME "/my_shared_memory"  // 共享内存对象名称
#define BUFFER_SIZE 1024              // 共享缓冲区大小

// 共享内存结构，包含数据缓冲区和同步标志
typedef struct {
    int ready;          // 发送方就绪标志
    char buffer[BUFFER_SIZE];  // 数据缓冲区
} SharedData;

int main() {
    int fd;
    SharedData *shared_data;
    char message[BUFFER_SIZE];

    // 创建或打开共享内存对象
    fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
    if (fd == -1) {
        perror("shm_open failed");
        exit(EXIT_FAILURE);
    }

    // 设置共享内存大小
    if (ftruncate(fd, sizeof(SharedData)) == -1) {
        perror("ftruncate failed");
        close(fd);
        shm_unlink(SHM_NAME);  // 出错时清理共享内存
        exit(EXIT_FAILURE);
    }

    // 将共享内存映射到进程地址空间
    shared_data = (SharedData *)mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (shared_data == MAP_FAILED) {
        perror("mmap failed");
        close(fd);
        shm_unlink(SHM_NAME);
        exit(EXIT_FAILURE);
    }

    // 关闭文件描述符，映射成功后不再需要
    close(fd);

    // 初始化共享内存
    shared_data->ready = 0;
    memset(shared_data->buffer, 0, BUFFER_SIZE);

    printf("共享内存发送端已启动，输入消息（输入'exit'退出）:\n");

    while (1) {
        // 等待接收方处理完上一条消息
        while (shared_data->ready) {
            usleep(100000);  // 等待100ms
        }

        // 从标准输入读取消息
        fgets(message, BUFFER_SIZE, stdin);
        message[strcspn(message, "\n")] = 0;  // 去除换行符

        // 复制消息到共享内存
        strncpy(shared_data->buffer, message, BUFFER_SIZE - 1);

        // 设置就绪标志，通知接收方
        shared_data->ready = 1;

        // 检查是否退出
        if (strcmp(message, "exit") == 0) {
            break;
        }
    }

    // 解除内存映射
    if (munmap(shared_data, sizeof(SharedData)) == -1) {
        perror("munmap failed");
        exit(EXIT_FAILURE);
    }

    // 删除共享内存对象
    if (shm_unlink(SHM_NAME) == -1) {
        perror("shm_unlink failed");
        exit(EXIT_FAILURE);
    }

    printf("发送端已退出\n");
    return 0;
}
